/*
 * Copyright (c) 2023 Cshoo Org. All Rights Reserved.
 */

package org.tattoo.workflow.api;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.cshoo.tattoo.embed.infra.entity.Response;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import org.tattoo.workflow.api.dto.*;
import org.tattoo.workflow.app.ProcurementAppService;
import org.tattoo.workflow.domain.consts.QueryProcurementMode;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

/**
 * @author 杨翼
 * @since 1.0
 */
@Api(tags = "采购订单接口")
@RequestMapping("/procurement")
@RestController
@Slf4j
public class ProcurementController {

    @Resource
    private ProcurementAppService procurementAppService;

    /**
     * 查询采购订单
     *
     * @param id 采购订单id
     * @return 采购订单
     */
    @GetMapping("/findProcurementOrder/{id}")
    @ApiOperation("查询采购订单")
    public ProcurementOrderResp findProcurementOrder(@PathVariable("id") Long id) {
        return procurementAppService.findProcurementOrder(id);
    }

    /**
     * 查询采购订单产品明细
     *
     * @param procurementOrderId 采购订单id
     * @return 采购订单产品明细
     */
    @GetMapping("/queryProcurementItems/{procurementOrderId}")
    @ApiOperation("查询采购明细")
    public List<ProcurementItemResp> queryProcurementItems(
            @PathVariable("procurementOrderId") Long procurementOrderId) {
        return procurementAppService.queryProcurementItems(procurementOrderId);
    }

    /**
     * 保存采购订单
     *
     * @param saveProcurementOrderReq 采购订单请求
     * @return 采购订单id
     */
    @PostMapping("/saveProcurementOrder")
    @ApiOperation("保存采购订单")
    public Response<Long> saveProcurementOrder(@RequestBody @Valid SaveProcurementOrderReq saveProcurementOrderReq)
            throws Exception {
        Long id = procurementAppService.saveProcurementOrder(saveProcurementOrderReq);
        return Response.<Long>builder().data(id).build();
    }

    /**
     * 保存采购订单明细，单条保存
     * 当前端有id传入，为修改操作，否则为新增操作
     *
     * @param saveProcurementItemReq 采购明细
     */
    @PostMapping("/saveProcurementItem")
    @ApiOperation("保存采购明细")
    public Response<?> saveProcurementItem(@RequestBody @Valid SaveProcurementItemReq saveProcurementItemReq)
            throws Exception {
        procurementAppService.saveProcurementItem(saveProcurementItemReq);
        return Response.builder().build();
    }

    /**
     * 删除采购明细
     *
     * @param id 采购明细id
     */
    @DeleteMapping("/deleteProcurementItem/{id}")
    @ApiOperation("删除采购明细")
    public Response<?> deleteProcurementItem(@PathVariable("id") Long id) {
        procurementAppService.deleteProcurementItem(id);
        return Response.builder().build();
    }

    /**
     * 提交采购订单，提交时将产生对应的工作流
     *
     * @param submitReq 提交请求
     */
    @PostMapping("/submitProcurementOrder")
    @ApiOperation("提交采购订单")
    public Response<?> submitProcurementOrder(@RequestBody SubmitReq submitReq) throws Exception {
        procurementAppService.submitProcurementOrder(submitReq);
        return Response.builder().build();
    }

    @PostMapping("/withdrawProcurementOrder/{id}")
    @ApiOperation("撤回采购订单")
    public Response<?> withdrawProcurementOrder(@PathVariable("id") Long id) throws Exception {
        procurementAppService.withdrawProcurementOrder(id);
        return Response.builder().build();
    }

    /**
     * 复核采购订单
     *
     * @param reviewReq 复核请求
     */
    @PostMapping("/reviewProcurementOrder")
    @ApiOperation("复核采购订单")
    public Response<?> reviewProcurementOrder(@RequestBody @Valid ReviewReq reviewReq) throws Exception {
        procurementAppService.reviewProcurementOrder(reviewReq);
        return Response.builder().build();
    }

    /**
     * 审批采购订单
     *
     * @param approveReq 审批请求
     */
    @PostMapping("/approveProcurementOrder")
    @ApiOperation("审批采购订单")
    public Response<?> approveProcurementOrder(@RequestBody ApproveReq approveReq) throws Exception {
        procurementAppService.approveProcurementOrder(approveReq);
        return Response.builder().build();
    }

    /**
     * 查询流程记录
     *
     * @param procurementOrderId 采购订单id
     */
    @GetMapping("/queryProcessRecords/{procurementOrderId}")
    @ApiOperation("查询流程记录")
    public List<ProcessRecordResp> queryProcessRecords(@PathVariable("procurementOrderId") Long procurementOrderId) {
        return procurementAppService.queryProcessRecords(procurementOrderId);
    }

    /**
     * 查询采购单
     *
     * @param queryMode 查询方式类型
     */
    @GetMapping("/queryProcurementOrders/{queryMode}")
    @ApiOperation("查询采购单")
    public List<ProcurementOrderResp> queryProcurementOrders(@PathVariable("queryMode") QueryProcurementMode queryMode)
            throws Exception {
        return procurementAppService.queryProcurementOrders(queryMode);
    }

    /**
     * 导出采购订单
     *
     * @return 采购订单excel
     * @throws Exception 异常
     */
    @GetMapping("/exportProcurementOrders")
    @ApiOperation("导出采购单")
    public ResponseEntity<StreamingResponseBody> exportProcurementOrders() throws Exception {
        HttpHeaders headers;
        StreamingResponseBody responseBody;
        try (ByteArrayOutputStream out = (ByteArrayOutputStream) procurementAppService.exportProcurementOrders()) {
            String fileName = "procurement-orders_" + DateFormatUtils.format(new Date(), "yyyyMMddHHmm") + ".xlsx";

            headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            ContentDisposition contentDisposition = ContentDisposition.attachment().filename(encodedFileName).build();
            headers.setContentDisposition(contentDisposition);
            headers.setContentLength(out.size());

            responseBody = out::writeTo;
        }

        return ResponseEntity.ok().headers(headers).body(responseBody);
    }
}
